#pragma once
#include<cstdint>
#include<functional>
#include<cassert>
#include<sys/epoll.h>
// #include "EventLoop.hpp" // Include the header file for EventLoop

class EventLoop; // Forward declaration of EventLoop

class Channel{
private:
    int _fd;
    EventLoop *_loop; //?
    uint32_t _events; //当前监控的事件
    uint32_t _revents; //当前连接触发的事件
    using EventCallback = std::function<void()>;
    EventCallback _read_callback;  //可写事件回调
    EventCallback _write_callback; //可读
    EventCallback _error_callback;  //错误
    EventCallback _close_callback;  //连接断开
    EventCallback _event_callback;  //任意事件
public:
    Channel(EventLoop* loop, int fd):_fd(fd),_events(0),_revents(0),_loop(loop){}
    int Fd() { return _fd; }
    uint32_t Events() { return _events; }  //获取监控的事件
    void SetREvents(uint32_t events) { _revents = events; }  //设置实际就绪的事件
    void SetReadCallback(const EventCallback &cb) { _read_callback = cb; }
    void SetWriteCallback(const EventCallback &cb) { _write_callback = cb; }
    void SetErrorCallback(const EventCallback &cb) { _error_callback = cb ;}
    void SetCloseCallback(const EventCallback &cb) { _close_callback = cb ; }
    void SetEventCallback(const EventCallback &cb) { _event_callback = cb ;}
    //判断监控事件
    bool ReadAble() { return (_events & EPOLLIN); }
    bool WriteAble() { return (_events & EPOLLOUT); }
    void EnableRead() { _events |= EPOLLIN; Update(); }
    void EnableWrite() { _events |= EPOLLOUT; Update(); }
    void DisableRead() { _events &= ~EPOLLIN; Update(); } 
    void DisableWrite() { _events &= ~EPOLLOUT; Update(); }
    void DisableAll() { _events = 0; Update(); }
    //移除监控
    void Remove();
    void Update();
    
    void HandleEvent(){
        //可读，对端关闭，紧急事件可读。
        if((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI)){
            if(_read_callback) _read_callback();
        }    
        if(_revents & EPOLLOUT){
            if(_write_callback) _write_callback();
        }else if(_revents & EPOLLERR){
            if(_error_callback) _error_callback();
        }else if(_revents & EPOLLHUP){
            if(_close_callback) _close_callback();
        }
        if(_event_callback) _event_callback();
    }
};

void Channel::Remove() {  _loop->RemoveEvent(this); } 
void Channel::Update() {  _loop->UpdateEvent(this); }

